package top.hcode.hoj;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.csv.CsvUtil;
import cn.hutool.core.text.csv.CsvWriter;
import cn.hutool.core.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
import org.nutz.http.Header;
import org.nutz.http.Http;
import org.nutz.http.Response;
import org.nutz.json.Json;
import org.nutz.lang.util.NutMap;
import org.sagacity.sqltoy.model.MapKit;
import top.hcode.hoj.common.LazyDao;
import top.hcode.hoj.pojo.entity.org.OrgUser;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 调用 bookshare-console 的接口，将天喻的用户和学生信息同步到阅读平台
 * 1. 将 org_user 表中待同步的用户的 flag0 字段设置为 0
 * 2. 设置同步参数，可以同步指定年级或者班级，不指定年级和班级则同步所有
 *
 * @author orangej
 * @since 2025/2/18
 */
@Slf4j
public class OrgUserExportApp extends BaseDbApp {

    private static final String outPath = "d:\\1123\\";
    private static LazyDao dao;

    // 参数设置
    private static final String schoolName = "武汉市光谷第十小学";       // 阅读平台学校名称
    private static final String campusId = "1882603449592655876";    // oj平台校区id
    private static final String gradeName = null;                   // 限制同步的年级：一年级
    private static final String className = null;                   // 限制同步的班级：一年级1班

    // update org_user set flag0 = 0;                                // 清除标记flag0，多次运行可以避免重复执行

    public static void main(String[] args) {
        dao = buildLazyDao();

        // 打印各年级的班级数量
        printClassNum(campusId);

        // 导出学生到csv
//        exportStudent(campusId);

        // 导出教师到csv
//        exportTeacher(campusId);

        // 通过接口添加学生
        sendStudentToBookshare(campusId);

        // 通过接口添加教师
        sendTeacherToBookshare(campusId);
    }

    private static void sendStudentToBookshare(String campusId) {
        String campusCode = dao.fetchString("select tree_code from org where id = ?", campusId);

        List<String> classIdList = dao.queryString(
                "select id from org where tree_code like :campusCode and org_type = 7 " +
                "#[and org_name like :gradeName] #[and org_name like :className]",
                MapKit.startOf("campusCode", campusCode)
                        .of("gradeName", gradeName)
                        .endOf("className", className));

        // 学生账号
        List<OrgUser> orgUserList = dao.selectList(OrgUser.class,
                "select * from org_user t0 where flag0 = 0 and user_type = 0 and " +
                "exists (select 1 from class_has_user where user_id = t0.id and org_id in (?))", classIdList);

        AtomicInteger count = new AtomicInteger(0);
        orgUserList.parallelStream().forEach(orgUser -> {
            List<String> classNameList = dao.queryString("select org_name from org where " +
                                                         "id in (select distinct org_id from class_has_user where user_id = ? and tree_code like ?)"
                    , orgUser.getId(), campusCode + "%");

            NutMap user = NutMap.NEW()
                    .addv("userType", 2)
                    .addv("uname", orgUser.getRealName())
                    .addv("username", orgUser.getUsername())
                    .addv("gender", getGenderCode(orgUser.getGender()))
                    .addv("avatarUrl", orgUser.getAvatar())
                    .addv("mobile", orgUser.getMobile());

            NutMap data = NutMap.NEW().addv("user", user)
                    .addv("schoolName", schoolName)
                    .addv("classNameList", classNameList);

            Response response = Http.post3("http://localhost:8120/api/import-ty-user", Json.toJson(data), Header.create(NutMap.NEW().addv("Content-Type", "application/json")), 60000);
            String content = response.getContent();
            if ("ok".equals(content)) {
                dao.runSql("update org_user set flag0 = 1 where id = ?", orgUser.getId());
            } else {
                log.error("failed : {}， {}", orgUser.getUsername(), content);
            }

            int current = count.getAndIncrement();
            if (current % 100 == 0) {
                log.error("finished : " + current + " / " + orgUserList.size());
            }
        });

        log.error("finished");
    }

    private static void sendTeacherToBookshare(String campusId) {
        String campusCode = dao.fetchString("select tree_code from org where id = ?", campusId);

        // 教师账号
        List<OrgUser> orgUserList = dao.selectList(OrgUser.class,
                "select * from org_user where flag0 = 0 and id in (\n" +
                "select distinct user_id from class_has_user where user_type = 1 and org_id in (\n" +
                "select id from org_class where campus_id = ?\n" +
                "))", campusId);

        AtomicInteger count = new AtomicInteger(0);
        orgUserList.parallelStream().forEach(orgUser -> {
            // 同一个学校的所有班级
            List<String> classNameList = dao.queryString("select distinct org_name from org where " +
                                                         "id in (select distinct org_id from class_has_user where user_id = ? and tree_code like ?)",
                    orgUser.getId(), campusCode.substring(0, 4) + "%");

            NutMap user = NutMap.NEW()
                    .addv("userType", 1)
                    .addv("uname", orgUser.getRealName())
                    .addv("username", orgUser.getUsername())
                    .addv("gender", getGenderCode(orgUser.getGender()))
                    .addv("avatarUrl", orgUser.getAvatar())
                    .addv("mobile", orgUser.getMobile());

            NutMap data = NutMap.NEW().addv("user", user)
                    .addv("schoolName", schoolName)
                    .addv("classNameList", classNameList);

            Response response = Http.post3("http://localhost:8120/api/import-ty-user", Json.toJson(data), Header.create(NutMap.NEW().addv("Content-Type", "application/json")), 60000);
            String content = response.getContent();
            if ("ok".equals(content)) {
                dao.runSql("update org_user set flag0 = 1 where id = ?", orgUser.getId());
            } else {
                log.error("failed : {}， {}", orgUser.getUsername(), content);
            }

            int current = count.getAndIncrement();
            if (current % 100 == 0) {
                log.error("finished : " + current + " / " + orgUserList.size());
            }
        });

        log.error("finished");
    }

    private static void exportTeacher(String campusId) {
        // 教师账号
        List<OrgUser> orgUserList = dao.selectList(OrgUser.class, "select * from org_user where id in (\n" +
                                                                  "select user_id from class_has_user where user_type = 1 and org_id in (\n" +
                                                                  "select id from org_class where campus_id = ?\n" +
                                                                  "))", campusId);
        CsvWriter writer = CsvUtil.getWriter(outPath + "teacher.csv", CharsetUtil.CHARSET_UTF_8);
        writer.setAlwaysDelimitText(true);
        writer.writeHeaderLine("uname", "userType", "username", "gender", "avatarUrl", "mobile");
        for (OrgUser orgUser : orgUserList) {
            writer.writeLine(orgUser.getRealName(), "1", orgUser.getUsername(),
                    getGenderCode(orgUser.getGender()), orgUser.getAvatar(), orgUser.getMobile());
        }
        writer.flush();
        writer.close();

        // 教师与班级对应关系
        List<NutMap> classHasUserList = dao.selectList(NutMap.class,
                "select username, class_name from class_has_user t0\n" +
                "         left join org_user t1 on t0.user_id = t1.id\n" +
                "         left join org_class t2 on t0.org_id = t2.id\n" +
                "         where t2.campus_id = ?\n" +
                "            and t0.user_type = 1;", campusId);
        writer = CsvUtil.getWriter(outPath + "teacher_class.csv", CharsetUtil.CHARSET_UTF_8);
        writer.setAlwaysDelimitText(true);
        writer.writeHeaderLine("username", "className");
        for (NutMap classHasUser : classHasUserList) {
            writer.writeLine(classHasUser.getString("username"), classHasUser.getString("className"));
        }
        writer.flush();
        writer.close();
    }

    private static void exportStudent(String campusId) {
        // 学生账号
        List<OrgUser> orgUserList = dao.selectList(OrgUser.class, "select * from org_user where id in (\n" +
                                                                  "select user_id from class_has_user where user_type = 0 and org_id in (\n" +
                                                                  "select id from org_class where campus_id = ?\n" +
                                                                  "))", campusId);
        CsvWriter writer = CsvUtil.getWriter(outPath + "student.csv", CharsetUtil.CHARSET_UTF_8);
        writer.setAlwaysDelimitText(true);
        writer.writeHeaderLine("uname", "userType", "username", "gender", "avatarUrl");
        for (OrgUser orgUser : orgUserList) {
            writer.writeLine(orgUser.getRealName(), "2", orgUser.getUsername(),
                    getGenderCode(orgUser.getGender()), orgUser.getAvatar());
        }
        writer.flush();
        writer.close();

        // 学生与班级对应关系
        List<NutMap> classHasUserList = dao.selectList(NutMap.class,
                "select username, class_name from class_has_user t0\n" +
                "         left join org_user t1 on t0.user_id = t1.id\n" +
                "         left join org_class t2 on t0.org_id = t2.id\n" +
                "         where t2.campus_id = ?\n" +
                "            and t0.user_type = 0;", campusId);
        writer = CsvUtil.getWriter(outPath + "student_class.csv", CharsetUtil.CHARSET_UTF_8);
        writer.setAlwaysDelimitText(true);
        writer.writeHeaderLine("username", "className");
        for (NutMap classHasUser : classHasUserList) {
            writer.writeLine(classHasUser.getString("username"), classHasUser.getString("className"));
        }
        writer.flush();
        writer.close();
    }

    static String getGenderCode(Integer gender) {
        if (gender == null) {
            return "S"; // 保密
        }
        switch (gender) {
            case 0:
                return "F"; // 女
            case 1:
                return "M"; // 男
            default:
                return "S"; // 保密
        }
    }

    private static void printClassNum(String campusId) {
        List<Integer> gradeNumList = dao.selectList(Integer.class, "select distinct grade_num from org_class " +
                                                                   "where campus_id = ? order by grade_num", campusId);
        for (Integer gradeNum : gradeNumList) {
            List<String> classNameList = dao.selectList(String.class,
                    "select distinct class_name from org_class " +
                    "where campus_id = ? and grade_num = ? order by class_num", campusId, gradeNum);
            System.out.println(CollUtil.join(classNameList, ", "));
            System.out.println();
        }
    }
}
